// <copyright file="MenuItemController.cs" company="Clever Software">
// Copyright (c) 2013, 2014 All Right Reserved, http://www.cleversoftware.by
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Clever Software</author>
// <email>info@cleversoftware.by</email>
// <date>2014-02-04</date> 
// <summary>CleverCMS source code</summary>

namespace CleverCMS.Web.Cms.Admin.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;

    using CleverCMS.Cms.Data.Entities;
    using CleverCMS.Cms.Services;
    using CleverCMS.Cms.Services.ViewModels;

    using CleverCMS.Core.Services;
    using CleverCMS.Core.Web.Filters;

    [Authorize(Roles = "Admin")]
    public class MenuItemController : Controller
    {
        private readonly MenuService m_menuService;
        private readonly PageService m_pageService;
        private readonly MenuItemService m_itemService;
        private readonly LoggingService m_loggingService;

        public MenuItemController(MenuService menuService,
                                  PageService pageService,
                                  MenuItemService itemService,
                                  LoggingService loggingService)
        {
            this.m_menuService = menuService;
            this.m_pageService = pageService;
            this.m_itemService = itemService;
            this.m_loggingService = loggingService;
        }

        public ActionResult List(int? id)
        {
            if (id != null)
            {
                var model = m_menuService.LoadMenu(id.Value);
                return View(model);
            }
            return View();
        }

        [HttpPost]
        public JsonResult ListMenuItems(int? id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
        {
            try
            {
                int count = 0;
                IEnumerable<CmsMenuItem> allPages = m_itemService.LoadAllMenuItems(jtStartIndex, jtPageSize, jtSorting, id, out count).ToList();
                return Json(new { Result = "OK", Records = allPages, TotalRecordCount = count });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }

        public ViewResult Edit(int? id)
        {
            if (id != null && id.Value != 0)
            {
                var menuItem = m_menuService.LoadMenuItem(id.Value);
                if (menuItem.Entry == null)
                    menuItem.Entry = new CmsPage();

                return View(new MenuItemAddModel
                                {
                                    MenuItem = menuItem,
                                    Entries = GetEntries(menuItem.EntryId),
                                    MenuTypes = GetMenuTypes(menuItem.MenuId),
                                    MenuItems = GetParentItems(menuItem.Id, menuItem.MenuId, menuItem.ParentId)
                                });
            }

            return View(new MenuItemAddModel
                            {
                                Entries = GetEntries(0),
                                MenuTypes = GetMenuTypes(1),
                                MenuItems = GetParentItems(0, 1, 0)
                            });
        }

        [ValidateInput(false)]
        [CurrentUserFilter]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(MenuItemAddModel forms)
        {
            try
            {
                bool isExternal = false;
                bool.TryParse(Request.Form.GetValues("MenuItem.IsExternalUrl")[0], out isExternal);

                if (isExternal)
                    forms.MenuItem.EntryId = null;
                else
                    forms.MenuItem.NavigateUrl = null;

                m_itemService.SaveMenuItem(forms.MenuItem);

                m_loggingService.Info("MenuItem saved.");
                var v = new { success = true, error = "", id = forms.MenuItem.Id };
                return Json(v);
            }
            catch (Exception exc)
            {
                var v = new { success = false, error = "Unknown error" };
                return Json(v);
            }
        }

        [HttpPost]
        [Authorize]
        public ActionResult Delete(int? Id)
        {
            if (!ModelState.IsValid)
            {
                var v = new { Result = "ERROR", Message = "", success = false, error = "Unknown error" };
                return Json(v);
            }

            try
            {
                if (Id != null)
                {
                    m_itemService.Delete(Id.Value);

                    m_loggingService.Warn("MenuItem deleted.");
                    var v = new { Result = "OK", success = true, error = "", menuItemId = Id };
                    return Json(v);
                }
                else
                {
                    var v = new { Result = "ERROR", Message = "", success = false, error = "Unknown error" };
                    return Json(v);
                }
            }
            catch (Exception exc)
            {
                var v = new { Result = "ERROR", Message = exc.Message, success = false, error = exc.Message };
                return Json(v);
            }
        }

        private SelectList GetEntries(int? entryId)
        {
            IEnumerable<CmsPage> entries = m_pageService.LoadAllPublished();

            if (entryId != null && entryId > 0)
                return new SelectList(entries, "Id", "PageTitle", entryId);
            else
                return new SelectList(entries, "Id", "PageTitle", 0);
        }

        private SelectList GetMenuTypes(int? menuId)
        {
            IEnumerable<CmsMenu> menues = m_menuService.LoadMenues();

            if (menuId != null && menuId > 0)
                return new SelectList(menues, "Id", "Type", menuId);

            return null;
        }

        private SelectList GetParentItems(int? id, int? menuId, int? parentId)
        {
            IEnumerable<CmsMenuItem> menuItems = m_menuService.LoadAllMenuItems();

            if (parentId != null && parentId > 0)
                return new SelectList(menuItems.Where(m => m.MenuId == menuId && m.Id != id), "Id", "Title", parentId);
            else
                return new SelectList(menuItems.Where(m => m.MenuId == menuId && m.Id != id), "Id", "Title", 0);
        }

        [HttpPost]
        [Authorize]
        public ActionResult ListMenues(int menuId)
        {
            IEnumerable<CmsMenuItem> menuItems = m_menuService.LoadAllMenuItems();
            return Json(menuItems.Where(m => m.MenuId == menuId).ToList());
        }

        [ChildActionOnly]
        public ActionResult AdminMenu()
        {
            int openMenuId = 0;
            if (Request.Cookies != null && Request.Cookies.Get("CleverCMS_Menu") != null)
            {
                String openIdString = Request.Cookies.Get("CleverCMS_Menu").Value;
                Int32.TryParse(openIdString, out openMenuId);
            }
            ICollection<CmsMenuItem> menues = m_itemService.LoadAllMenuItems().Where(m => m.MenuId == 2)
                .OrderBy(x => x.ParentId == null).ThenBy(c => c.SortOrder).ToList();
            ViewBag.OpenMenuID = openMenuId;
            return PartialView(menues);
        }

        #region jsTree logic

        #region ajax lazy loading

        private static List<NodeViewModel> AddChildNodes(int parentId, IEnumerable<CmsMenuItem> nodes)
        {
            var gJsTreeArray = nodes.Select(node => new NodeViewModel
            {
                data = node.Title + " (Date: " + node.CreatedAt.ToString("g") + ")",
                state = "closed",
                IdServerUse = node.Id,
                children = null,
                attr = new AttributeViewModel { id = node.Id.ToString(), selected = false }
            }).ToList();
            return gJsTreeArray;
        }

        [HttpPost]
        public ActionResult GetAllNodes(int id, int? menuType)
        {
            if (id != -1)
            {
                var nodes = m_itemService.LoadAllMenuItems().Where(x => (x.MenuId == menuType.Value && x.ParentId == id));
                return Json(AddChildNodes(id, nodes));
            }

            var gJsTreeArray = new List<NodeViewModel>();
            var roots = m_itemService.LoadAllMenuItems().Where(x => (x.MenuId == menuType.Value && x.ParentId == null)).ToList();
            gJsTreeArray.AddRange(AddChildNodes(0, roots));
            return Json(gJsTreeArray);
        }



        #endregion

        [HttpPost]
        public ActionResult Rename(int id, string newTitle)
        {
            if (id != 0)
            {
                m_itemService.Rename(id, newTitle);
                return Json(new { result = "OK", success = true, message = "Node is renamed" });
            }
            return Json(new { result = "ERROR", success = false, message = "Id is null (or 0)" });
        }

        [HttpPost]
        public ActionResult Remove(int id)
        {
            if (id != 0 && id != 15)
            {
                m_itemService.Delete(id);
                m_loggingService.Warn("MenuItem deleted.");
                return Json(new { result = "OK", success = true, message = "Node is deleted" });
            }
            return Json(new { result = "ERROR", success = false, message = "Id is null (or 0)" });
        }

        [HttpPost]
        public ActionResult Create(int parentId, string title, int menuType)
        {
            try
            {
                var menuItem = new CmsMenuItem
                {
                    Title = title,
                    ParentId = parentId,
                    NavigateUrl = "/",
                    EntryId = null,
                    Visible = true,
                    SortOrder = 0,
                    MenuId = menuType
                };
                m_itemService.SaveMenuItem(menuItem);
                m_loggingService.Info("MenuItem saved.");
                return Json(new { result = "OK", success = true, message = "Node is created!", id = menuItem.Id });
            }
            catch (Exception)
            {
                return Json(new { result = "ERROR", success = false, message = "Some errors!" });
            }
        }

        [HttpPost]
        public ActionResult MoveNode(int id, int? parentId)
        {
            var item = m_itemService.LoadAllMenuItems()
                                    .Where(x => x.Id == id)
                                    .FirstOrDefault();

            item.ParentId = parentId;
            m_itemService.SaveMenuItem(item);

            return null;
        }

        #region Old jsTree logic

        public ActionResult Tree()
        {
            var model = new MenuTreeViewModel
            {
                MenuItems = m_menuService.LoadAllMenuItems().ToList(),
                MenuTypes = m_menuService.LoadMenues().ToList()
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult RemoveItem(int id, string type)
        {
            if (id != 0)
            {
                if (type == "drive")
                    m_menuService.Remove(id);
                else 
                    if (type == "folder")
                        m_itemService.Delete(id);

                return Json(new { result = "OK", success = true, message = "Node is deleted" });
            }
            return Json(new { result = "ERROR", success = false, message = "Id is null (or 0)" });
        }

        [HttpPost]
        public ActionResult RenameItem(int id, string type, string newTitle)
        {
            if (id != 0)
            {
                if (type == "drive")
                    m_menuService.RenameMenuType(id, newTitle);
                else 
                    if (type == "folder")
                        m_itemService.Rename(id, newTitle);

                return Json(new { result = "OK", success = true, message = "Node is renamed" });
            }
            return Json(new { result = "ERROR", success = false, message = "Id is null (or 0)" });
        }

        #endregion

        #endregion
    }
}